/*
MIT License

Copyright (c) 2022 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,

https://bmstu.codes/lsx/simodo/loom
*/

#include "simodo/interpret/builtins/hosts/fuze/FuzeAnalyzer.h"
#include "simodo/interpret/AnalyzeException.h"

#include "simodo/inout/convert/functions.h"

// inline const u16string EXCEEDED = u"The number of errors has exceeded the allowable limit";

namespace
{
    simodo::interpret::SemanticDataCollector_null null_semantic_collector;
}

namespace simodo::interpret::builtins
{

    FuzeAnalyzer::FuzeAnalyzer(Interpret * inter, 
                            std::string grammar_name,
                            parser::Grammar & grammar,
                            parser::TableBuildMethod method,
                            bool need_strict_rule_consistency)
        : FuzeInterpret_abstract(inter, grammar_name, grammar, method, need_strict_rule_consistency)
        , _collector(null_semantic_collector)
    {
    }

    FuzeAnalyzer::FuzeAnalyzer(Interpret * inter, 
                            SemanticDataCollector_interface & collector,
                            std::string grammar_name,
                            parser::Grammar & grammar,
                            parser::TableBuildMethod method,
                            bool need_strict_rule_consistency)
        : FuzeInterpret_abstract(inter, grammar_name, grammar, method, need_strict_rule_consistency)
        , _collector(collector)
    {
    }

    InterpretState FuzeAnalyzer::executeGlobalScript(const inout::Token & label, const ast::Node & script)
    {
        InterpretState state = FuzeInterpret_abstract::executeGlobalScript(label, script);

        _collector.collectNameDeclared({label.lexeme(), {variable::ValueType::Function, variable::Object {{
                {u"@", variable::InternalFunction {&script, {}}},
                {{}, variable::ValueType::Null},
            }}}, label.location()});

        return state;
    }

    InterpretState FuzeAnalyzer::executeProduction(const inout::Token & production, 
                                    const std::vector<inout::Token> & pattern, 
                                    const inout::Token & direction_token,
                                    const ast::Node & action)
    {
        InterpretState state = FuzeInterpret_abstract::executeProduction(production, pattern, direction_token, action);

        _productions.insert({production.lexeme(),{production, pattern}});
        _directions.push_back(direction_token);

        return state;
    }

    InterpretState FuzeAnalyzer::executeRef(const inout::Token & token, const std::u16string & ref)
    {
        _collector.collectRef(token, ref);
        return FuzeInterpret_abstract::executeRef(token, ref);
    }
}